package com.atao.baokede.controller;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.atao.baokede.config.AliPayConfig;
import com.atao.baokede.constant.OrderConstant;
import com.atao.baokede.pojo.ChargeOrder;
import com.atao.baokede.pojo.ItemOrder;
import com.atao.baokede.pojo.Result;
import com.atao.baokede.pojo.User;
import com.atao.baokede.service.ChargeOrderService;
import com.atao.baokede.service.ItemOrderService;
import com.atao.baokede.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

import static com.atao.baokede.constant.OrderConstant.STATUS_PAID;
import static com.atao.baokede.constant.OrderConstant.STATUS_UNPAID;

/**
 * 阿里云支付接口
 */
@RestController
@RequestMapping("/alipay")
public class AliPayController {
    // 支付宝沙箱网关地址
    private static final String GATEWAY_URL = "https://openapi-sandbox.dl.alipaydev.com/gateway.do";
    private static final String FORMAT = "JSON";
    private static final String CHARSET = "UTF-8";
    //签名方式
    private static final String SIGN_TYPE = "RSA2";

    @Autowired
    private AliPayConfig aliPayConfig;

    @Autowired
    private ChargeOrderService chargeOrderService;

    @Autowired
    private ItemOrderService itemOrderService;
    @Autowired
    private UserService userService;

    @Value("${baokede.returnToAddressAfterPayment}")
    private String returnToAddressAfterPayment;

    /**
     * 用户余额支付
     *
     * @param orderNo 订单号
     * @throws Exception
     */
    @GetMapping("/chargePay")  //  /alipay/pay?orderNo=xxx
    public void pay(@RequestParam Long orderNo, HttpServletResponse httpResponse) throws Exception {
        // 查询订单信息
        ChargeOrder orders = chargeOrderService.selectByOrderNo(orderNo);
        if (orders == null) {
            return;
        }
        // 1. 创建Client，通用SDK提供的Client，负责调用支付宝的API
        AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL, aliPayConfig.getAppId(),
                aliPayConfig.getAppPrivateKey(), FORMAT, CHARSET, aliPayConfig.getAlipayPublicKey(), SIGN_TYPE);

        // 2. 创建 Request并设置Request参数
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();  // 发送请求的 Request类
        request.setNotifyUrl(aliPayConfig.getNotifyUrl());

        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", orders.getOrderNo());
        bizContent.put("total_amount", orders.getRequestAmount());
        bizContent.put("subject", "余额充值");
        bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
        request.setBizContent(bizContent.toJSONString());

        request.setReturnUrl(returnToAddressAfterPayment+"/account/profile"); // 支付完成后自动跳转到本地页面的路径
        // 执行请求，拿到响应的结果，返回给浏览器
        String form = "";
        try {
            form = alipayClient.pageExecute(request).getBody(); // 调用SDK生成表单
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        httpResponse.setContentType("text/html;charset=" + CHARSET);
        httpResponse.getWriter().write(form);// 直接将完整的表单html输出到页面
        httpResponse.getWriter().flush();
        httpResponse.getWriter().close();
    }

    /**
     * 用户商品订单支付
     *
     * @param orderNo 订单号
     * @throws Exception
     */
    @GetMapping("/chargePayItem")  //  /alipay/pay?orderNo=xxx
    public void payItem(@RequestParam Long orderNo, HttpServletResponse httpResponse) throws Exception {
        // 查询订单信息
        ItemOrder orders = itemOrderService.selectByOrderNo(orderNo);

        if (orders != null && orders.getStatus() == STATUS_UNPAID) {
            // 1. 创建Client，通用SDK提供的Client，负责调用支付宝的API
            AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL, aliPayConfig.getAppId(),
                    aliPayConfig.getAppPrivateKey(), FORMAT, CHARSET, aliPayConfig.getAlipayPublicKey(), SIGN_TYPE);

            // 2. 创建 Request并设置Request参数
            AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();  // 发送请求的 Request类
            request.setNotifyUrl(aliPayConfig.getNotifyUrl());

            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no", orders.getOrderId());
            bizContent.put("total_amount", orders.getAmount());
            bizContent.put("subject", "商品订单支付");
            bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
            request.setBizContent(bizContent.toJSONString());

            request.setReturnUrl("http://ataotao.top/layout"); // 支付完成后自动跳转到本地页面的路径
            // 执行请求，拿到响应的结果，返回给浏览器
            String form = "";
            try {
                form = alipayClient.pageExecute(request).getBody(); // 调用SDK生成表单
            } catch (AlipayApiException e) {
                e.printStackTrace();
            }
            httpResponse.setContentType("text/html;charset=" + CHARSET);
            httpResponse.getWriter().write(form);// 直接将完整的表单html输出到页面
            httpResponse.getWriter().flush();
            httpResponse.getWriter().close();
        } else {
            return;
        }
    }

    /**
     * 支付宝回调接口（无需前端调用）
     *
     * @param request 无
     * @throws Exception
     */
    @PostMapping("/notify")  // 注意这里必须是POST接口
    public void payNotify(HttpServletRequest request) throws Exception {
        if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
            System.out.println("=========支付宝异步回调========");

            Map<String, String> params = new HashMap<>();
            Map<String, String[]> requestParams = request.getParameterMap();
            for (String name : requestParams.keySet()) {
                params.put(name, request.getParameter(name));
            }

            String sign = params.get("sign");
            String content = AlipaySignature.getSignCheckContentV1(params);
            boolean checkSignature = AlipaySignature.rsa256CheckContent(content, sign, aliPayConfig.getAlipayPublicKey(), "UTF-8"); // 验证签名
            // 支付宝验签
            if (checkSignature) {
                // 验签通过
                System.out.println("交易名称: " + params.get("subject"));
                System.out.println("交易状态: " + params.get("trade_status"));
                System.out.println("支付宝交易凭证号: " + params.get("trade_no"));
                System.out.println("商户订单号: " + params.get("out_trade_no"));
                System.out.println("交易金额: " + params.get("total_amount"));
                System.out.println("买家在支付宝唯一id: " + params.get("buyer_id"));
                System.out.println("买家付款时间: " + params.get("gmt_payment"));
                System.out.println("买家付款金额: " + params.get("buyer_pay_amount"));

                if (params.get("subject").equals("余额充值")) {
                    String tradeNo = params.get("out_trade_no");
                    // 更新订单状态为已支付，设置支付信息
                    ChargeOrder chargeOrder = chargeOrderService.selectByOrderNo(Long.valueOf(tradeNo));
                    chargeOrder.setStatus(1);
                    chargeOrder.setCompletedTime(LocalDateTime.now());
                    //将chargeOrder中的属性全部打印出来
                    System.out.println(chargeOrder.toString());
                    chargeOrderService.modify(chargeOrder);
                } else if (params.get("subject").equals("商品订单支付")) {
                    ItemOrder itemOrder = new ItemOrder();
                    itemOrder.setOrderId(Long.valueOf(params.get("trade_no")));
                    itemOrder.setStatus(STATUS_PAID);
                    itemOrder.setPayTime(LocalDateTime.now());
                    itemOrderService.modify(itemOrder);
                }
            }
        }
    }


    /**
     * 商品订单退款
     *
     * @param orderNo
     * @return 无
     */
    @PutMapping("/itemRefund")
    public Result itemRefund(Long orderNo) throws AlipayApiException {
        // 查询订单信息
        ItemOrder orders = itemOrderService.selectByOrderNo(orderNo);

        if (ObjectUtil.isNull(orders)) {
            return Result.error("订单不存在");
        }
        // 1. 创建Client，通用SDK提供的Client，负责调用支付宝的API
        AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL, aliPayConfig.getAppId(),
                aliPayConfig.getAppPrivateKey(), FORMAT, CHARSET, aliPayConfig.getAlipayPublicKey(), SIGN_TYPE);

        // 2. 创建 Request并设置Request参数
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        request.setNotifyUrl(aliPayConfig.getNotifyUrl());


        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", orders.getOrderId());  // 我们自己生成的订单编号  必须是不重复的退款订单号
        bizContent.put("refund_amount", orders.getAmount()); // 订单的总金额
        bizContent.put("out_request_no", IdUtil.fastSimpleUUID());   // 随机数
        request.setBizContent(bizContent.toString());


        // 退款调用接口
        AlipayTradeRefundResponse response = alipayClient.execute(request);
        if (response.isSuccess()) {
            itemOrderService.updateStatus(orderNo, OrderConstant.STATUS_REFUNDED);
            return Result.success();
        }

        return Result.error("支付宝退款失败");
    }

    /**
     * 余额订单退款
     *
     * @param orderNo
     * @return 无
     */
    @PutMapping("/orderRefund")
    public Result orderRefund(Long orderNo) throws AlipayApiException {
        // 查询订单信息
        ChargeOrder order = chargeOrderService.selectByOrderNo(orderNo);
        if (ObjectUtil.isNull(order)) {
            return Result.error("订单不存在");
        }
        User user = userService.getUserInfoById(order.getUserId());
        if (user.getBalance().compareTo(order.getRequestAmount()) < 0) {
            // 用户余额不足
            return Result.error("用户余额不足，无法完成退款");
        }
        // 1. 创建Client，通用SDK提供的Client，负责调用支付宝的API
        AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL, aliPayConfig.getAppId(),
                aliPayConfig.getAppPrivateKey(), FORMAT, CHARSET, aliPayConfig.getAlipayPublicKey(), SIGN_TYPE);

        // 2. 创建 Request并设置Request参数
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        request.setNotifyUrl(aliPayConfig.getNotifyUrl());


        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", order.getOrderNo());  // 我们自己生成的订单编号  必须是不重复的退款订单号
        bizContent.put("refund_amount", order.getRequestAmount()); // 订单的总金额
        bizContent.put("out_request_no", IdUtil.fastSimpleUUID());   // 随机数
        request.setBizContent(bizContent.toString());


        AlipayTradeRefundResponse response = alipayClient.execute(request);
        if (response.isSuccess()) {
            chargeOrderService.updateStatus(orderNo, 2);
            userService.reduceBalance(order.getUserId(), order.getRequestAmount());
            return Result.success();
        }else{
            // 打印详细错误信息
            String errorCode = response.getSubCode(); // 错误码
            String errorMsg = response.getSubMsg();  // 错误描述
            System.out.println("退款失败，错误码: " + errorCode + ", 错误信息: " + errorMsg);
            return Result.error("支付宝退款失败，错误信息: " + errorMsg);
        }
    }
}
